package repeat.personal.util;

import feign.Response;
import org.apache.commons.lang.ArrayUtils;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import repeat.personal.exception.PopupException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created by Zhanggq on 2019/6/6.
 */
public interface FileDownloadTool {

    Logger logger = LoggerFactory.getLogger(FileDownloadTool.class);

    /**
     * 文件下载(默认文件名)
     *
     * @param request
     * @param response
     * @param ins
     * @throws IOException
     */
    static void download(HttpServletRequest request, HttpServletResponse response, InputStream ins) throws IOException {
        download(request, response, ins, "");
    }

    /**
     * 文件下载(流),指定文件名
     *
     * @param request
     * @param response
     * @param ins
     * @param displayName
     * @throws IOException
     */
    static void download(HttpServletRequest request, HttpServletResponse response, InputStream ins, String displayName)
            throws IOException {

        String userAgent = request.getHeader("User-Agent");
        boolean isIE = (userAgent != null) && (userAgent.toLowerCase().indexOf("msie") != -1);
        buildResponse(response);
        String displayFilename = displayName.substring(displayName.lastIndexOf("_") + 1);
        displayFilename = displayFilename.replace(" ", "_");
        encodeName(response, displayFilename, isIE);
        try (ServletOutputStream os = response.getOutputStream()) {
            int count;
            byte data[] = new byte[1024];
            while ((count = ins.read(data, 0, 1024)) != -1) {
                os.write(data, 0, count);
            }
            os.flush();
        } catch (Exception e) {
            logger.error("异常信息：{}", e);
        } finally {
            if (ins != null) {
                ins.close();
            }
        }
    }

    /**
     * feign response流文件下载
     *
     * @param res
     * @param feignRes
     * @throws IOException
     */
    static void download(HttpServletResponse res, Response feignRes) {
        Map<String, Collection<String>> headers = feignRes.headers();
        for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
            Collection<String> value = entry.getValue();
            if (value.iterator().hasNext()) {
                res.addHeader(entry.getKey(), value.iterator().next());
            }
        }
        try (InputStream is = feignRes.body().asInputStream();
             OutputStream os = res.getOutputStream();
             BufferedInputStream in = new BufferedInputStream(is)) {
            IOUtils.copy(in, os);
        } catch (Exception e) {
            logger.error("异常信息：{}", e);
            throw new PopupException("文件下载失败!");
        }
    }

    /**
     * 文件下载(二进制)
     *
     * @param request
     * @param response
     * @param displayName
     * @param bytes
     * @throws IOException
     */
    static void download(HttpServletRequest request, HttpServletResponse response, String displayName, byte[] bytes)
            throws IOException {

        if (ArrayUtils.isEmpty(bytes)) {
            response.setContentType("text/html;charset=utf-8");
            response.setCharacterEncoding("utf-8");
            response.getWriter().write("您下载的文件不存在！");
            return;
        }
        String userAgent = request.getHeader("User-Agent");
        boolean isIE =
                (userAgent != null) && (userAgent.toLowerCase().indexOf("msie") != -1 || userAgent.toLowerCase().indexOf("edge") != -1);
        buildResponse(response);
        response.setContentLength((int) bytes.length);
        String displayFilename = displayName.replace(" ", "_");
        encodeName(response, displayFilename, isIE);
        try (OutputStream os = response.getOutputStream();
             BufferedInputStream is = new BufferedInputStream(new ByteArrayInputStream(bytes));
        ) {
            IOUtils.copy(is, os);
        } catch (Exception e) {
            logger.error("异常信息：{}", e);
        }
    }

    /**
     * 文件打包下载
     *
     * @param request
     * @param response
     * @param displayName
     * @param mapstream
     * @throws IOException
     */
    static void downloadZip(HttpServletRequest request, HttpServletResponse response, String displayName,
                            Map<String, InputStream> mapstream) throws IOException {

        String userAgent = request.getHeader("User-Agent");
        boolean isIE = (userAgent != null) && (userAgent.toLowerCase().indexOf("msie") != -1);
        buildResponse(response);
        encodeName(response, displayName, isIE);
        BufferedInputStream is = null;
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            ZipOutputStream out = new ZipOutputStream(os);
            for (Map.Entry<String, InputStream> entry : mapstream.entrySet()) {
                is = new BufferedInputStream(entry.getValue());
                out.putNextEntry(new ZipEntry(entry.getKey()));
                IOUtils.copy(is, out);
                out.closeEntry();
            }
            out.close();
        } catch (Exception e) {
            logger.error("异常信息：{}", e);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

    /**
     * 文件名编码
     *
     * @param response
     * @param displayFilename
     * @param isIE
     * @throws IOException
     */
    static void encodeName(HttpServletResponse response, String displayFilename, boolean isIE) throws IOException {
        if (isIE) {
            displayFilename = URLEncoder.encode(displayFilename, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=\"" + displayFilename + "\"");
        } else {
            displayFilename = new String(displayFilename.getBytes("UTF-8"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + displayFilename);
        }
    }

    /**
     * 构建响应头部
     *
     * @param response
     */
    static void buildResponse(HttpServletResponse response) {
        response.reset();
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "must-revalidate, no-transform");
        response.setDateHeader("Expires", 0L);
        response.setContentType("application/x-download");
    }
}
